package cn.angleline.cloudhub.easbi

import cn.angleline.cloudhub.easbi.util.EncryptUtils
import cn.angleline.cloudhub.easbi.yzj.entity.AccessToken
import cn.angleline.cloudhub.easbi.yzj.entity.RequestEntity
import cn.angleline.cloudhub.easbi.yzj.entity.TableInfoData
import cn.angleline.cloudhub.easbi.yzj.entity.TokenParam
import com.fasterxml.jackson.databind.ObjectMapper
import com.google.common.cache.Cache
import kotlinx.coroutines.experimental.async
import okhttp3.*
import org.apache.commons.codec.digest.DigestUtils
import org.apache.commons.lang3.StringUtils
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.beans.factory.annotation.Value
import org.springframework.stereotype.Component
import java.util.*


@Component
class CloudhubBIComponent {

    @Autowired
    private lateinit var objectMapper: ObjectMapper

    @Autowired
    private lateinit var okHttpClient: OkHttpClient

    @Autowired
    private lateinit var tokenCache: Cache<String, String>

    @Autowired
    private lateinit var encryptUtils: EncryptUtils

    @Value("\${cloudhub.aes-key}")
    private lateinit var aesKey: String

    @Value("\${cloudhub.aes-key}")
    private lateinit var globalAesKey: String

    @Value("\${cloudhub.eid}")
    private lateinit var eid: String

    @Value("\${cloudhub.app-id}")
    private lateinit var appId: String

    @Value("\${cloudhub.secret}")
    private lateinit var secret: String

    fun saveTableInfoData(data: List<Map<String, Any>>) {
        data.chunked(500).forEach {
            val tableInfoData = TableInfoData(eid, encryptUtils.uuid(), encryptUtils.uuid(),
                    ReportApiService.PaymentTable.categoryId, ReportApiService.PaymentTable.tableInfoId,
                    objectMapper.writeValueAsString(it))
            val encryptData = encryptUtils.aesEncryptData(objectMapper.writeValueAsString(tableInfoData), aesKey)
            val requestEntity = RequestEntity(encryptData)

            val urlBuilder = HttpUrl.Builder()
            val requestBuilder = Request.Builder()
            urlBuilder.scheme("https")
            urlBuilder.host("www.yunzhijia.com")
            urlBuilder.addPathSegment("gateway")
            urlBuilder.addPathSegment("open")
            urlBuilder.addPathSegment("linkerp")
            urlBuilder.addPathSegment("customizedapi")
            urlBuilder.addPathSegment("saveTableInfoData")
            urlBuilder.addQueryParameter("accessToken", getAccessToken())
            requestBuilder.url(urlBuilder.build())
            requestBuilder.post(RequestBody.create(MediaType.parse("application/json"),
                    objectMapper.writeValueAsString(requestEntity)))
            okHttpClient.newCall(requestBuilder.build()).enqueue(OkHttpCallbackStub())
        }
    }

    fun getAccessToken(): String {
        return tokenCache.get("accessToken") {
            val requestBuilder = Request.Builder()
            val urlBuilder = HttpUrl.Builder()
            urlBuilder.scheme("https")
            urlBuilder.host("www.yunzhijia.com")
            urlBuilder.addPathSegment("gateway")
            urlBuilder.addPathSegment("oauth2")
            urlBuilder.addPathSegment("token")
            urlBuilder.addPathSegment("getTeamAccessToken")
            requestBuilder.url(urlBuilder.build())
            val nonceStr = encryptUtils.uuid()
            val timeStamp = System.currentTimeMillis().toString()
            val signature = sign(appId, nonceStr, timeStamp, secret)
            val tokenEntity = TokenParam(appId, nonceStr, signature, timeStamp)

            val body = objectMapper.writeValueAsString(tokenEntity)
            requestBuilder.post(RequestBody.create(MediaType.parse("application/json"), body))
            val response = okHttpClient.newCall(requestBuilder.build()).execute()
            val responseBody = response.body()
            if (response.isSuccessful && responseBody != null) {
                val accessToken = objectMapper.readValue(
                        responseBody.byteStream(), AccessToken::class.java)
                accessToken.data.accessToken
            } else {
                throw IllegalArgumentException("appId或secret不正确")
            }
        }
    }


    fun sign(vararg data: String): String {
        Arrays.sort(data)
        return DigestUtils.sha1Hex(StringUtils.join(*data))
    }
}